package org.bing.engine.jmx;

import static java.lang.management.ManagementFactory.CLASS_LOADING_MXBEAN_NAME;
import static java.lang.management.ManagementFactory.COMPILATION_MXBEAN_NAME;
import static java.lang.management.ManagementFactory.MEMORY_MXBEAN_NAME;
import static java.lang.management.ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME;
import static java.lang.management.ManagementFactory.RUNTIME_MXBEAN_NAME;
import static java.lang.management.ManagementFactory.THREAD_MXBEAN_NAME;
import static java.lang.management.ManagementFactory.newPlatformMXBeanProxy;

import java.io.IOException;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.CompilationMXBean;
import java.lang.management.MemoryMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;

public class ManagementProxyClient {
    private MBeanServerConnection server;

    private ClassLoadingMXBean classLoadingMBean = null;
    private CompilationMXBean compilationMBean = null;
    private MemoryMXBean memoryMBean = null;
    private OperatingSystemMXBean operatingSystemMBean = null;
    private RuntimeMXBean runtimeMBean = null;
    private ThreadMXBean threadMBean = null;

    public ManagementProxyClient(JMXConnector conn) {
        try {
            server = conn.getMBeanServerConnection();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public String getProperty(String property) throws IOException {
        return this.getRuntimeMXBean().getSystemProperties().get(property);
    }

    public synchronized ClassLoadingMXBean getClassLoadingMXBean() throws IOException {
        if (classLoadingMBean == null) {
            classLoadingMBean = newPlatformMXBeanProxy(server, CLASS_LOADING_MXBEAN_NAME, ClassLoadingMXBean.class);
        }
        return classLoadingMBean;
    }

    public synchronized CompilationMXBean getCompilationMXBean() throws IOException {
        if (compilationMBean == null) {
            compilationMBean = newPlatformMXBeanProxy(server, COMPILATION_MXBEAN_NAME, CompilationMXBean.class);
        }
        return compilationMBean;
    }

    public synchronized MemoryMXBean getMemoryMXBean() throws IOException {
        if (memoryMBean == null) {
            memoryMBean = newPlatformMXBeanProxy(server, MEMORY_MXBEAN_NAME, MemoryMXBean.class);
        }
        return memoryMBean;
    }

    public synchronized RuntimeMXBean getRuntimeMXBean() throws IOException {
        if (runtimeMBean == null) {
            runtimeMBean = newPlatformMXBeanProxy(server, RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
        }
        return runtimeMBean;
    }

    public synchronized ThreadMXBean getThreadMXBean() throws IOException {
        if (threadMBean == null) {
            threadMBean = newPlatformMXBeanProxy(server, THREAD_MXBEAN_NAME, ThreadMXBean.class);
        }
        return threadMBean;
    }

    public synchronized OperatingSystemMXBean getOperatingSystemMXBean() throws IOException {
        if (operatingSystemMBean == null) {
            operatingSystemMBean = newPlatformMXBeanProxy(server, OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);
        }
        return operatingSystemMBean;
    }

    public <T> T getMXBean(ObjectName objName, Class<T> interfaceClass) throws IOException {
        return newPlatformMXBeanProxy(server, objName.toString(), interfaceClass);

    }
}
